﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SyncList.Winner;
using System.Diagnostics;
using System.Threading;
using SyncList.Business.ValueObject;
using SyncList.Business;
using SyncList.Business.Persistence;
using SyncList.Win;
using SyncList.UserInterface;
using Microsoft.Win32;
using System.IO;

namespace SyncList
{
    /// <summary>
    /// Logique d'interaction pour Window1.xaml
    /// </summary>
    public partial class WindowScan : Window, IWriter
    {

        #region Attributs


        private bool _mustStop = false;

        private Data _currentData = null;
                
        /// <summary>
        /// Indique si le scan est en cours
        /// </summary>
        private ScanState _state = ScanState.Stopped;


        private long minSize = 500 * 1024; // 50 * 1024 * 1024;           

        #endregion

        #region Constructeur

        /// <summary>
        /// Constructeur
        /// </summary>
        public WindowScan()
        {
            InitializeComponent();

            this.BtnStop.Click += new RoutedEventHandler(BtnStop_Click);
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
            this.BtnScan.Click += new RoutedEventHandler(BtnScan_Click);
            this.BtnCreateNew.Click += new RoutedEventHandler(BtnCreateNew_Click);
            this.Host.CloseList += new EventHandler(Host_CloseList);
            this.BtnSelectFile.Click += new RoutedEventHandler(BtnSelectFile_Click);

            this.BlockLoad.AllowDrop = true;
            this.BlockLoad.Drop += new DragEventHandler(BlockLoad_Drop);
            this.BtnLoad.Click += new RoutedEventHandler(BtnLoad_Click);
            this.BtnClose.Click += new RoutedEventHandler(BtnClose_Click);

            CurrentData = null;

            StartHelper.Start(MenuBar);
            MenuBar.ExitAction = () => this.Close();
        }


       


        /// <summary>
        /// Fermeture des données courantes
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Host_CloseList(object sender, EventArgs e)
        {
            if (State != ScanState.Stopped)
            {
                MessageBox.Show("Impossible to close while scan is in progress");
            }
            else
            {
                CurrentData = null;
            }
        }


        
        #endregion

        #region Evénements


        /// <summary>
        /// Créer une nouvelle liste
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnCreateNew_Click(object sender, RoutedEventArgs e)
        {
            // - Sécurité
            if (CurrentData == null)
            {
                string newName = this.TextBoxNewListName.Text;

                Int32 minSize;

                if (!Int32.TryParse(this.TextBoxMinSize.Text, out minSize))
                {
                    MessageBox.Show("La taille minimum n'est pas lisible");
                    return;
                }                 

                if (!String.IsNullOrWhiteSpace(newName))
                {
                    newName = newName.Trim();

                    Data data = new Data();
                    data.Title = newName;
                    data.UserName = MemoryStorage.Instance.Settings.UserName;
                    data.XmlFileName = newName + ".syl";
                    CurrentData = data;
                }
            }
        }



        /// <summary>
        /// Choisir une liste
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnSelectFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Listes (*.syl)|*.syl|Tous les fichiers (*.*)|*.*||";
            dialog.FilterIndex = 0;
            if (dialog.ShowDialog(this) == true)
            {
                string path = dialog.FileName;
                this.TextBoxExistingFileName.Text = path;

                // - Chargement automatique
                if(!String.IsNullOrWhiteSpace(path)&& File.Exists(path))
                    LoadFile(path);
            }
        }


        /// <summary>
        /// Lancer le scan
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnScan_Click(object sender, RoutedEventArgs e)
        {
            State = ScanState.InProgress;
            ThreadStart start = new ThreadStart(ThreadTask);
            Thread thread = new Thread(start);
            thread.Start();   
        }


        /// <summary>
        /// Demande d'interruption du traitement
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnStop_Click(object sender, RoutedEventArgs e)
        {
            State = ScanState.Stopping;
            _mustStop = true;
            
            //BtnStop.IsEnabled = false;
        }


        /// <summary>
        /// Loaded
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Window1_Loaded(object sender, RoutedEventArgs e)
        {


                
        }



        /// <summary>
        /// Charger un fichier dont le nom a été copié/collé ou tapé manuellement
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnLoad_Click(object sender, RoutedEventArgs e)
        {
            LoadFile(this.TextBoxExistingFileName.Text);
        }


        /// <summary>
        /// Fermer la liste courante
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnClose_Click(object sender, RoutedEventArgs e)
        {
            CurrentData = null;
        }



        /// <summary>
        /// Drop d'une liste dans la zone
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BlockLoad_Drop(object sender, DragEventArgs e)
        {
            //Récupère le path du fichier que l'on vient de glisser-déposer sur l'interface de comparaison !
            string[] _filePath = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (_filePath == null || !_filePath.Count().Equals(1))
                return;

            if (!File.Exists(_filePath[0]))
                return;

            //on récupère un FileInfo sur le fichier qui vient d'être déposé.
            FileInfo _currentFileDropped = new FileInfo(_filePath[0]);

            // On vérifie que le fichier est bien au format XML
            if (!_currentFileDropped.Extension.ToLower().Equals(".syl"))
            {
                MessageBox.Show("This is not a SyncList file !");
                return;
            }

            //Apres vérification de la structure XML du fichier droppé, soit on l'accepte...soit....bah pas !!
            //si on l'accepte, on créé l'élément Data correspondant.

            LoadFile(_currentFileDropped.FullName);

            //Business.ServiceAccessor.RegistryService.Read

        }



        /// <summary>
        /// Charger un fichier
        /// </summary>
        /// <param name="fileName"></param>
        public void LoadFile(string fileName)
        {

            if (String.IsNullOrWhiteSpace(fileName) || !File.Exists(fileName))
            {
                MessageBox.Show("Please verify file path");
                return;
            }

            string userName = MemoryStorage.Instance.Settings.UserName;

            Data data = ServiceAccessor.ImportService.ImportList(fileName);
            data.XmlFileName = fileName;
            if (!String.IsNullOrWhiteSpace(userName))
            {
                if (!userName.Equals(data.UserName))
                {
                    MessageBox.Show("You can't open another one's list in Scan program");
                    return;
                }
            }
            CurrentData = data;

        }



        #endregion

        #region Propriétés


        /// <summary>
        /// Indique si le scan est en cours
        /// </summary>
        private ScanState State
        {
            get { return (_state); }
            set {
                _state = value;
                ChangeVisualState();
             
            }
        }


        /// <summary>
        /// Mettre à jour l'affichage des boutons
        /// </summary>
        private void ChangeVisualState()
        {
            BtnScan.IsEnabled = ((_state == ScanState.Stopped) && (CurrentData != null));
            BtnStop.IsEnabled = (_state == ScanState.InProgress);
            BtnClose.IsEnabled = ((CurrentData != null) && (_state == ScanState.Stopped));
        }

        /// <summary>
        /// Données courantes
        /// </summary>
        public Data CurrentData
        {
            get { return (_currentData); }
            set 
            {
                _currentData = value;                
                

                Dispatcher.BeginInvoke(new Action(delegate()
                {
                    this.Host.Visibility = Bool2Visible(value != null);
                    this.BlockCreateNew.Visibility = Bool2Visible(value == null);
                    this.BlockLoad.Visibility = Bool2Visible(value == null);

                    this.Host.DataContext = value;

                    ChangeVisualState();
                    //this.CurrentFileList.DataContext = value;
                }));
            }
        }

        #endregion

        #region Méthodes

        /// <summary>
        /// Exécuté dans le Thread
        /// </summary>
        private void ThreadTask()
        {

            if (CurrentData == null) return; // Sécurité

            Data data = CurrentData;

            
            //string[] baseFolders = new string[] { @"L:\FILMS" };
            //string title = "Films";


            while (!_mustStop)
            {

                IImportService import = ServiceAccessor.ImportService;
                
                //CurrentData = import.ImportXml(data.XmlFileName);
                //if (CurrentData == null)
                //    CurrentData = new Data();

                data.FileFilter.MinSize = minSize;
                foreach (string baseFolder in data.Folders)
                {
                    if (!data.Folders.Contains(baseFolder))
                        data.Folders.Add(baseFolder);
                }
                data.Title = data.Title;

                FileFilter filter = new FileFilter();
                filter.MinSize = minSize;

                FileScanner scanner = new FileScanner();
                int count = scanner.Scan(data.Files, data.Folders.ToArray(), filter, 0, new TimeSpan(0, 3, 0), ref _mustStop, this);
                if (count == 0) break;


                ExecuteUI(() => Host.RefreshFileList());

                IExportService export = ServiceAccessor.ExportService;
                ExportInfo info = export.ExportList(data, data.XmlFileName, minSize);
                if (info != null)
                {
                    WriteLine(info.dateTimeCaption + " Export of " + info.FileCount + " files : " + info.TotalSizeCaption);
                }
            }

            ExecuteUI(() => State = ScanState.Stopped);
            if (_mustStop)
            {               
                MessageBox.Show("STOPPED");
            }
            else
                MessageBox.Show("END");

        }



        /// <summary>
        /// Vider le Log
        /// </summary>
        public void Clear()
        {
            this.TextBoxLog.Document.Blocks.Clear();
        }

       

        /// <summary>
        /// Ecrire une ligne
        /// </summary>
        /// <param name="txt"></param>
        public void WriteLine(string txt)
        {
            if (!txt.EndsWith(Environment.NewLine))
                txt += Environment.NewLine;

                            //this.TextBoxLog.AppendText(txt + Environment.NewLine);
            ExecuteUI(() => this.TextBoxLog.AppendText(txt)); // + Environment.NewLine));
            //this.Dispatcher.BeginInvoke(new Action(delegate()
            //{
                
            //}), null);
            ////this.TextBoxLog.Selection.Start = this.TextBoxLog.Selection.
        }



        /// <summary>
        /// Exécuter dans le Thread de l'UI
        /// </summary>
        /// <param name="action"></param>
        private void ExecuteUI(Action action)
        {
            this.Dispatcher.BeginInvoke(action, null);            
        }



        private Visibility Bool2Visible(bool value)
        {
            Visibility visible = System.Windows.Visibility.Visible;
            if (!value)
                visible = System.Windows.Visibility.Collapsed;
            return (visible);
        }

        #endregion




    }
}
